package com.boss.core;

import com.boss.core.common.Artifact;
import com.boss.core.common.Target;
import com.boss.core.common.TargetLinuxBox;
import com.boss.core.manage.BossProperty;
import com.boss.core.manage.BossPropertyDescriptor;
import com.boss.core.util.BossGlobalUtil;
import com.boss.core.util.BossUtil;
import com.boss.Messages;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.Functions;
import hudson.model.Action;
import hudson.model.Describable;
import hudson.model.AbstractModelObject;
import hudson.model.Hudson;
import hudson.model.User;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import java.awt.HeadlessException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

import javax.servlet.ServletException;


/**
 * This class implements an extension point to Hudson
 *
 * @author Momin Noor Khan
 */

public abstract class Boss extends AbstractModelObject implements ExtensionPoint, Action, Describable<Boss> {
    /**
     * Gets the image file used as icon for BOSS.
     */
    public String getIconFileName() {
        return BossConstants.BOSS_ICON;
    }

    /**
     * GEt url name
     * @return
     */
    public String getUrlName() {
        return getClass().getSimpleName();
    }

    /**
     * Default display name.
     */
    public String getDisplayName() {
        return getClass().getSimpleName();
    }

    /**
     * Get search url
     * @return
     */
    public String getSearchUrl() {
        return null;
    }

    /**
     * Default form submit action
     */
    public String getSubmitAction() {
        return "submit";
    }

    /**
     * GEt post-submit landing view
     * @return
     */
    public String getPostSubmitView() {
        return BossConstants.POST_SUBMIT_VIEW;
    }

    /**
     * Source files associated with this.
     */
    public List<SourceFile> getSourceFiles() {
        return Arrays.asList(new SourceFile(getClass().getSimpleName() + ".java"), new SourceFile("index.jelly"));
    }

    /**
     * Binds {@link SourceFile}s into URL.
     */
    public void doSourceFile(StaplerRequest req, StaplerResponse rsp) throws IOException {
        String name = req.getRestOfPath().substring(1); // Remove leading slash i.e /
        for (SourceFile sf : getSourceFiles()) {
            if (sf.name.equals(name)) {
                sf.doIndex(rsp);
                return;
            }
        }
        rsp.sendError(StaplerResponse.SC_NOT_FOUND);
    }

    /**
     * Returns a paragraph of natural text that describes the BOSS
     */
    public abstract String getDescription();

    /**
     * Gets the descriptor associated with this class
     */
    public BossDescriptor getDescriptor() {
        return (BossDescriptor) Hudson.getInstance().getDescriptorOrDie(getClass());
    }

    /**
     * Returns all the registered {@link Boss}s.
     */
    public static ExtensionList<Boss> all() {
        return Hudson.getInstance().getExtensionList(Boss.class);
    }

    /**
     * Get property descriptors of boss
     * @return
     */
    public static List<BossPropertyDescriptor> getBossPropertyDescriptors() {
        return BossProperty.all();
    }

    /**
     * UI method: used in GIS views
     * Finds out if the logged in user is authorized to perform GIS tasks.
     */
    public static boolean isAuthorizedGISUser() {
        String user = "";
        char delimiter = '\n';

        if (User.current().getId() != null) {
            user = User.current().getId();
        }

        List<String> gisUsers = BossUtil.getPropertyValues2(BossConstants.PROJECT_GIS, BossConstants.AUTHORIZED_USERS, delimiter, false, false);

        if (!StringUtils.isBlank(user) && !gisUsers.isEmpty() && gisUsers.contains(user)) {
            return true;
        }
        return false;
    }

    /**
     * UI method: index.jelly
     * @param project
     * @return
     */
    public List<String> getTasks(String project) {
        return BossUtil.getPropertyValues2(project, BossConstants.TASKS_KEY, '\n', true, false);
    }

    /**
     * UI method: index.jelly
     * @param task
     * @return
     */
    public String getTaskView(String task) {
        String view = "";
        if (task.contains("-")) {
            String tmpArray[] = StringUtils.splitByWholeSeparator(task, "-");
            for (int i = 0; i < tmpArray.length; i++) {
                if (i != 0) {
                    tmpArray[i] = StringUtils.capitalize(tmpArray[i]);
                }
                view += tmpArray[i];
            }
        } else {
            view = task;
        }
        view = view.concat(BossConstants.SUFFIX_VIEW);
        try {
            if (!Functions.hasView(this, view)) {
                view = BossConstants.DUMMY_VIEW;
            }
        } catch (HeadlessException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return view;
    }

    /**
     * @author Momin Noor Khan
     */
    public class SourceFile {
        public final String name;

        public SourceFile(String name) {
            this.name = name;
        }

        /**
         * Resolve to url
         * @return
         */
        public URL resolve() {
            return Boss.this.getClass().getResource(name.endsWith(".jelly") ? Boss.this.getClass().getSimpleName() + "/" + name : name);
        }

        /**
         * Serves this source file.
         * To-Do : FIND OUT WHAT IS THE REAL PURPOSE OF THIS METHOD????
         */
        public void doIndex(StaplerResponse rsp) throws IOException {
            //rsp.setContentType("text/plain;charset=UTF-8");
            //copy(resolve().openStream(),rsp.getOutputStream());
        }
    }
}
